#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <malloc.h>
#include <stdio.h>
#include <stdbool.h>
#include <iphlpapi.h>
#include <stdlib.h>

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")

void PrintNetworkStats() {
  DWORD dwSize = 0;
  MIB_IFTABLE *pIfTable = NULL;

  // 获取所需内存大小
  GetIfTable(pIfTable, &dwSize, FALSE);

  pIfTable = (MIB_IFTABLE *) malloc(dwSize);
  if (pIfTable == NULL) {
    printf("Memory allocation failed\n");
    return;
  }

  // 获取网络接口表
  if (GetIfTable(pIfTable, &dwSize, FALSE) == ERROR_BUFFER_OVERFLOW) {
    free(pIfTable);
    pIfTable = (MIB_IFTABLE *) malloc(dwSize);
    if (pIfTable == NULL) {
      printf("Memory allocation failed\n");
      return;
    }
  }

  if (GetIfTable(pIfTable, &dwSize, FALSE) != NO_ERROR) {
    printf("Failed to get interface table\n");
    free(pIfTable);
    return;
  }

  for (DWORD i = 0; i < pIfTable->dwNumEntries; i++) {
    printf("Interface %u:\n", i + 1);
    printf("\tIndex: %u\n", pIfTable->table[i].dwIndex);
    printf("\tType: %u\n", pIfTable->table[i].dwType);
    printf("\tSpeed: %llu bps\n", pIfTable->table[i].dwSpeed);
    printf("\tPhysAddr Len: %u\n", pIfTable->table[i].dwPhysAddrLen);
    printf("\tAdmin Status: %u\n", pIfTable->table[i].dwAdminStatus);
    printf("\tOper Status: %u\n", pIfTable->table[i].dwOperStatus);
    printf("\tLast Change: %llu\n", pIfTable->table[i].dwLastChange);
    printf("\tIn Octets: %llu\n", pIfTable->table[i].dwInOctets);
    printf("\tOut Octets: %llu\n", pIfTable->table[i].dwOutOctets);
    printf("\tIn UcastPkts: %llu\n", pIfTable->table[i].dwInUcastPkts);
    printf("\tOut UcastPkts: %llu\n", pIfTable->table[i].dwOutUcastPkts);
    printf("\tIn Discards: %llu\n", pIfTable->table[i].dwInDiscards);
    printf("\tOut Discards: %llu\n", pIfTable->table[i].dwOutDiscards);
    printf("\tIn Errors: %llu\n", pIfTable->table[i].dwInErrors);
    printf("\tOut Errors: %llu\n", pIfTable->table[i].dwOutErrors);
    printf("\tIn Unknown Protos: %llu\n", pIfTable->table[i].dwInUnknownProtos);
    printf("\n");
  }

  free(pIfTable);
}

void PrintNetworkSpeed() {
  DWORD size = 0;
  PMIB_IFTABLE pIfTable = NULL;

  // 获取所需缓冲区大小
  GetIfTable(pIfTable, &size, FALSE);

  // 分配缓冲区
  pIfTable = (MIB_IFTABLE *) malloc(size);
  if (!pIfTable) {
    printf("内存分配失败\\n");
    return;
  }

  // 获取网络接口表
  if (GetIfTable(pIfTable, &size, FALSE) == ERROR_BUFFER_OVERFLOW) {
    free(pIfTable);
    pIfTable = (MIB_IFTABLE *) malloc(size);
    if (!pIfTable) {
      printf("内存分配失败\\n");
      return;
    }
    GetIfTable(pIfTable, &size, FALSE);
  }

  // 初始化初始值
  ULONG64 initialBytesSent = 0, initialBytesReceived = 0;
  for (DWORD i = 0; i < pIfTable->dwNumEntries; i++) {
    initialBytesSent += pIfTable->table[i].dwOutOctets;
    initialBytesReceived += pIfTable->table[i].dwInOctets;
  }

  while (true) {
    Sleep(1000); // 每隔一秒获取一次数据

    // 重新获取网络接口表
    if (GetIfTable(pIfTable, &size, FALSE) != NO_ERROR) {
      printf("获取网络接口表失败\\n");
      break;
    }

    // 计算每秒发送和接收的字节数
    ULONG64 currentBytesSent = 0, currentBytesReceived = 0;
    for (DWORD i = 0; i < pIfTable->dwNumEntries; i++) {
      currentBytesSent += pIfTable->table[i].dwOutOctets;
      currentBytesReceived += pIfTable->table[i].dwInOctets;
    }

    ULONG64 bytesSentPerSecond = currentBytesSent - initialBytesSent;
    ULONG64 bytesReceivedPerSecond = currentBytesReceived - initialBytesReceived;

    // 打印结果
    printf("发送速度: %llu 字节/秒, 接收速度: %llu 字节/秒\n", bytesSentPerSecond, bytesReceivedPerSecond);

    // 更新初始值
    initialBytesSent = currentBytesSent;
    initialBytesReceived = currentBytesReceived;
  }

  free(pIfTable);
}

int main() {
  system("chcp 65001");

  WSADATA wsaData;
  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
    printf("WSAStartup failed\n");
    return -1;
  }

  PrintNetworkStats();
  PrintNetworkSpeed();

  WSACleanup();
  return 0;
}